package com.crm.system.service.impl.permissionManagement;

import com.crm.common.model.Enum.StatusCodeEnum;
import com.crm.common.util.CommonUtils;
import com.crm.model.entity.sys.UserAccount;
import com.crm.model.entity.sys.permissionManagement.SysCompany;
import com.crm.model.entity.sys.permissionManagement.SysCompanyPermission;
import com.crm.model.entity.sys.permissionManagement.SysMenu;
import com.crm.model.entity.sys.permissionManagement.SysMenuPermission;
import com.crm.model.vo.permissionManagement.SysMenuVO;
import com.crm.service.sys.permissionManagement.SysCompanyDbService;
import com.crm.service.sys.permissionManagement.SysMenuDbService;
import com.crm.system.service.permissionManagement.SysCompanyPermissionService;
import com.crm.system.service.permissionManagement.SysMenuPermissionService;
import com.crm.system.service.permissionManagement.SysMenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单--业务层
 * @Author yincuimei
 * @Date 2020/12/7 14:59
 */
@Service
public class SysMenuServiceImpl implements SysMenuService {
    @Autowired
    private SysMenuDbService sysMenuDbService;

    @Autowired
    private SysCompanyDbService sysCompanyDbService;

    @Autowired
    private SysMenuPermissionService sysMenuPermissionService;

    @Autowired
    private SysCompanyPermissionService sysCompanyPermissionService;

    /**
     * 加载用户模块
     * @param userAccount
     * @return
     */
    @Override
    public Map<String,List<SysMenuVO>> selectUserPermSysMenuList(UserAccount userAccount){
        List<SysMenuVO> userSysMenuVOS = new LinkedList<SysMenuVO>();
        List<SysMenu> userSysMenus =new ArrayList<>();
        //判断是否是财务 deptId 3/4暂时标识为财务
        if ("3".equals(userAccount.getDeptId()) || "4".equals(userAccount.getDeptId())){
            userSysMenus = sysMenuDbService.selectSysMenuByAccountId((short) StatusCodeEnum.NORMAL_CODE.getState(),userAccount.getAccountId(),"2","3");

        }else {
            userSysMenus = sysMenuDbService.selectSysMenuByAccountId((short) StatusCodeEnum.NORMAL_CODE.getState(),userAccount.getAccountId(),"2","2");
        }
        for (SysMenu dbItem :userSysMenus) {
            userSysMenuVOS.add(new SysMenuVO(dbItem));
        }
        List<SysMenuVO> userSysMenuList = getChildSysMenuList(userSysMenuVOS, "0");

        Map<String,List<SysMenuVO>> userSysMenuVOsMap = new HashMap<String,List<SysMenuVO>>();
        int count = sysMenuDbService.selectManagerSyMenuCountByAccountId((short) StatusCodeEnum.NORMAL_CODE.getState(),userAccount.getAccountId(),"2","1");
        if(count > 0){
            userSysMenuVOsMap.put("existManagerSysMenu",userSysMenuList);
        }else{
            userSysMenuVOsMap.put("notExistManagerSysMenu",userSysMenuList);
        }
        return userSysMenuVOsMap;
    }

    /**
     * 加载管理模块
     * @param userAccount
     * @return
     */
    @Override
    public List<SysMenuVO> selectManagerPermSysMenuList(UserAccount userAccount){
        List<SysMenuVO> userSysMenuVOS = new LinkedList<SysMenuVO>();
        List<SysMenu> userSysMenus = sysMenuDbService.selectSysMenuByAccountId((short) StatusCodeEnum.NORMAL_CODE.getState(),userAccount.getAccountId(),"2","1");
        for (SysMenu dbItem :userSysMenus) {
            userSysMenuVOS.add(new SysMenuVO(dbItem));
        }
        List<SysMenuVO> userSysMenuList = getChildSysMenuList(userSysMenuVOS, "0");
        return userSysMenuList;
    }

    /**
     * 超级管理员--查询用户模块菜单
     * @return
     */
    @Override
    public List<SysMenuVO> selectAllUserPermSysMenuList() {
        List<SysMenuVO> userSysMenuVOS = new LinkedList<SysMenuVO>();
        //查询用户模块菜单
        List<SysMenu> userSysMenus = sysMenuDbService.selectAllSysMenu((short) StatusCodeEnum.NORMAL_CODE.getState(),"2","2");
        for (SysMenu dbItem :userSysMenus) {
            userSysMenuVOS.add(new SysMenuVO(dbItem));
        }
        List<SysMenuVO> userSysMenuList = getChildSysMenuList(userSysMenuVOS, "0");
        return userSysMenuList;
    }

    /**
     * 超级管理员--查询管理模块菜单
     * @return
     */
    @Override
    public List<SysMenuVO> selectAllManagerPermSysMenuList() {
        List<SysMenuVO> managerSysMenuVOList = new LinkedList<SysMenuVO>();
        //查询管理模块菜单
        List<SysMenu> manageSysMenus = sysMenuDbService.selectAllSysMenu((short) StatusCodeEnum.NORMAL_CODE.getState(),"2","1");
        for (SysMenu dbItem :manageSysMenus) {
            managerSysMenuVOList.add(new SysMenuVO(dbItem));
        }
        List<SysMenuVO> managerSysMenuList = getChildSysMenuList(managerSysMenuVOList, "0");
        return managerSysMenuList;
    }

    /**
     * 超级管理员--查询所有左侧菜单
     * @return
     */
    @Override
    public Map<String,List<SysMenuVO>> selectAllPermSysMenuList() {
        Map<String,List<SysMenuVO>> sysMenuMap = new HashMap<>();
        List<SysMenuVO> manageSysMenuVOS = new LinkedList<SysMenuVO>();
        //查询管理模块菜单
        List<SysMenu> manageSysMenus = sysMenuDbService.selectAllSysMenu((short) StatusCodeEnum.NORMAL_CODE.getState(),"2","1");
        for (SysMenu dbItem :manageSysMenus) {
            manageSysMenuVOS.add(new SysMenuVO(dbItem));
        }
        List<SysMenuVO> manageSysMenuList = getChildSysMenuList(manageSysMenuVOS, "0");
        if( manageSysMenuList != null && manageSysMenuList.size() > 0){
            sysMenuMap.put("managementModule",manageSysMenuList);
        }

        List<SysMenuVO> userSysMenuVOS = new LinkedList<SysMenuVO>();
        //查询用户模块菜单
        List<SysMenu> userSysMenus = sysMenuDbService.selectAllSysMenu((short) StatusCodeEnum.NORMAL_CODE.getState(),"2","2");
        for (SysMenu dbItem :userSysMenus) {
            userSysMenuVOS.add(new SysMenuVO(dbItem));
        }
        //查询财务系统菜单
        List<SysMenu> financeSysMenus = sysMenuDbService.selectAllSysMenu((short) StatusCodeEnum.NORMAL_CODE.getState(),"2","3");
        for (SysMenu dbItem :financeSysMenus) {
            userSysMenuVOS.add(new SysMenuVO(dbItem));
        }
        List<SysMenuVO> userSysMenuList = getChildSysMenuList(userSysMenuVOS, "0");
        if(userSysMenuList != null && userSysMenuList.size() > 0){
            sysMenuMap.put("userModule",userSysMenuList);
        }
        return sysMenuMap;
    }

    /**
     * 根据父节点的ID获取所有子节点
     * @param sysMenuVOList 分类表
     * @param menuPid 传入的父节点ID
     * @return String
     */
    public List<SysMenuVO> getChildSysMenuList(List<SysMenuVO> sysMenuVOList, String menuPid)
    {
        List<SysMenuVO> childSysMenuList = new ArrayList<SysMenuVO>();
        for (Iterator<SysMenuVO> iterator = sysMenuVOList.iterator(); iterator.hasNext();)
        {
            SysMenuVO sysMenuVO = iterator.next();
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (sysMenuVO.getMenuPid().equals(menuPid)){
                recursionFn(sysMenuVOList, sysMenuVO);
                childSysMenuList.add(sysMenuVO);
            }
        }
        return childSysMenuList;
    }

    /**
     * 递归列表
     * @param sysMenuVOList
     * @param sysMenuVO
     */
    private void recursionFn(List<SysMenuVO> sysMenuVOList, SysMenuVO sysMenuVO)
    {
        // 得到子节点列表
        List<SysMenuVO> childSysMenuList = getChildSysMenuList(sysMenuVOList, sysMenuVO);
        sysMenuVO.setChildSysMenuList(childSysMenuList);
        for (SysMenuVO childSysMenu : childSysMenuList)
        {
            if (hasChild(sysMenuVOList, childSysMenu))
            {
                // 判断是否有子节点
                Iterator<SysMenuVO> it = childSysMenuList.iterator();
                while (it.hasNext())
                {
                    SysMenuVO sysMenuVO1 = it.next();
                    recursionFn(sysMenuVOList, sysMenuVO1);
                }
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysMenuVO> getChildSysMenuList(List<SysMenuVO> sysMenuVOList, SysMenuVO sysMenuVO)
    {
        List<SysMenuVO> childSysMenuList = new ArrayList<SysMenuVO>();
        Iterator<SysMenuVO> iterator = sysMenuVOList.iterator();
        while (iterator.hasNext())
        {
            SysMenuVO n = iterator.next();
            if (n.getMenuPid().equals(sysMenuVO.getMenuId()))
            {
                childSysMenuList.add(n);
            }
        }
        return childSysMenuList;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysMenuVO> sysMenuVOList, SysMenuVO sysMenuVO)
    {
        return getChildSysMenuList(sysMenuVOList, sysMenuVO).size() > 0;
    }


    /**
     * 获取权限组功能树
     * @return
     */
    public Map<String, List<Map<String, Object>>> getPermissionTree(String permissionGroupId){
        Map<String, List<Map<String, Object>>> permissionTreeMap = new HashMap<>();
        Map<String, List<SysMenuVO>> permSysMenuListMap = selectAllPermSysMenuList();
        Map<String, List<SysMenuPermission>> menuIdGroup = null;
        Map<String, List<SysCompanyPermission>> menuPermissionIdGroup = null;
        //获取所有公司
        List<SysCompany> sysCompanyList = sysCompanyDbService.selectSysCompanyList();
        //根据省份编码进行分组
        Map<String, List<SysCompany>> sysCompanyGroup = sysCompanyList.stream().collect(Collectors.groupingBy(sysCompany -> sysCompany.getProvinceCode()));
        //根据权限组ID查询菜单-权限组关联表
        if(!StringUtils.isBlank(permissionGroupId)){
            List<SysMenuPermission> sysMenuPermissionList = sysMenuPermissionService.selectSysMenuPermissionList(permissionGroupId);
            //根据菜单Id进行分组
            menuIdGroup = sysMenuPermissionList.stream().collect(Collectors.groupingBy(sysMenuPermission -> sysMenuPermission.getMenuId()));
            //根据权限组ID查询菜单-权限组关联表主键
            List<String> menuPermissionIdList = sysMenuPermissionService.selectMenuPermissionIdList(permissionGroupId);
            //根据菜单-权限组关联表主键集合查询公司-权限关联表
            List<SysCompanyPermission> sysCompanyPermissionList = sysCompanyPermissionService.selectSysCompanyPermissionList(menuPermissionIdList);
            menuPermissionIdGroup = sysCompanyPermissionList.stream().collect(Collectors.groupingBy(sysCompanyPermission -> sysCompanyPermission.getMenuPermissionId()));
        }

        if(permSysMenuListMap != null){
            if(permSysMenuListMap.get("managementModule")!= null && permSysMenuListMap.get("managementModule").size() > 0){
                List<SysMenuVO> managementModule = permSysMenuListMap.get("managementModule");
                List<Map<String, Object>> managementModuleList = getStringListMap(managementModule, sysCompanyGroup, menuIdGroup, menuPermissionIdGroup);
                permissionTreeMap.put("managementModule",managementModuleList);
            }
            if(permSysMenuListMap.get("userModule")!= null && permSysMenuListMap.get("userModule").size() > 0){
                List<SysMenuVO> userModule = permSysMenuListMap.get("userModule");
                List<Map<String, Object>> userModuleList = getStringListMap(userModule, sysCompanyGroup, menuIdGroup, menuPermissionIdGroup);
                permissionTreeMap.put("userModule",userModuleList);
            }
        }
        return permissionTreeMap;
    }

    /**
     * 获取权限组菜单Map集合
     * @param module
     * @return
     */
    private List<Map<String, Object>> getStringListMap(List<SysMenuVO> module, Map<String, List<SysCompany>> sysCompanyGroup,
                                                       Map<String, List<SysMenuPermission>> menuIdGroup,
                                                       Map<String, List<SysCompanyPermission>> menuPermissionIdGroup) {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        Map<String, Object> map;
        for (SysMenuVO sysMenuVO : module) {
            map = new HashMap<>();
            String menuId = sysMenuVO.getMenuId();
            String menuName = sysMenuVO.getMenuName();
            if("回款管理".equals(menuName)){
                menuName = "回款管理（财务账号才有效）";
            }
            map.put("id", menuId);
            map.put("pId", "0");
            map.put("name", menuName);
            map.put("menuType", "0");
            map.put("groupId", menuId);
            if(isMenuChecked(menuIdGroup, menuId)){
                map.put("checked", true);
            }
            list.add(map);
            List<SysMenuVO> childSysMenuList = sysMenuVO.getChildSysMenuList();
            getMaps(list, sysCompanyGroup, sysMenuVO, childSysMenuList, menuIdGroup, menuPermissionIdGroup);
        }
        return list;
    }

    /**
     * 递归获取权限组菜单
     * @param list
     * @param sysCompanyGroup
     * @param sysMenuVO
     * @param childSysMenuList
     * @return
     */
    private List<Map<String, Object>> getMaps(List<Map<String, Object>> list, Map<String, List<SysCompany>> sysCompanyGroup,
                                              SysMenuVO sysMenuVO, List<SysMenuVO> childSysMenuList,
                                              Map<String, List<SysMenuPermission>> menuIdGroup,
                                              Map<String, List<SysCompanyPermission>> menuPermissionIdGroup) {
        Map<String, Object> map;
        if(childSysMenuList != null && !childSysMenuList.isEmpty()){
            for (SysMenuVO menuVO : childSysMenuList) {
                String menuName = menuVO.getMenuName();
                if("创建权限组".equals(menuName)){
                    continue;
                }
                map = new HashMap<>();
                String menuId = menuVO.getMenuId();
                map.put("id", menuId);
                map.put("pId", sysMenuVO.getMenuId());
                map.put("name", menuName);
                map.put("menuType", "1");
                map.put("groupId", menuId);
                if(isMenuChecked(menuIdGroup, menuId)){
                    map.put("checked", true);
                }
                list.add(map);
                String id = CommonUtils.getGUID();
                map = new HashMap<>();
                map.put("id", id);
                map.put("pId", menuId);
                map.put("name", "全部地区");
                map.put("menuType", "2");
                map.put("groupId", menuId);
                String permissionRange = "";
                if(menuIdGroup != null && !menuIdGroup.isEmpty()){
                    List<SysMenuPermission> sysMenuPermissions = menuIdGroup.get(menuId);
                    if(sysMenuPermissions != null && !sysMenuPermissions.isEmpty()){
                        Short permissionRange1 = sysMenuPermissions.get(0).getPermissionRange();
                        permissionRange = permissionRange1 != null ? permissionRange1.toString() : "";
                    }
                }
                if(isRegionChecked(menuIdGroup, menuPermissionIdGroup, menuId) || "2".equals(permissionRange)){
                    map.put("checked", true);
                }
                list.add(map);
                for(Map.Entry<String, List<SysCompany>> entry : sysCompanyGroup.entrySet()){
                    List<SysCompany> sysCompanyS = entry.getValue();
                    String provinceCode = sysCompanyS.get(0).getProvinceCode() + CommonUtils.getGUID();
                    String provinceName = sysCompanyS.get(0).getProvinceName();
                    map = new HashMap<>();
                    map.put("id", provinceCode);
                    map.put("pId", id);
                    map.put("name", provinceName);
                    map.put("menuType", "3");
                    map.put("groupId", menuId);
                    if(isProvinceChecked(menuIdGroup, menuPermissionIdGroup, menuId, sysCompanyS) || "2".equals(permissionRange)){
                        map.put("checked", true);
                    }
                    list.add(map);
                    if(sysCompanyS != null && !sysCompanyS.isEmpty()){
                        for (SysCompany sysCompany : sysCompanyS) {
                            String companyId = sysCompany.getCompanyId();
                            map = new HashMap<>();
                            map.put("id", companyId);
                            map.put("pId", provinceCode);
                            map.put("name",sysCompany.getCompanyName());
                            map.put("menuType", "4");
                            map.put("groupId", menuId);
                            if(isCompanyChecked(menuIdGroup, menuPermissionIdGroup, menuId, companyId) || "2".equals(permissionRange)){
                                map.put("checked", true);
                            }
                            list.add(map);
                        }
                    }
                }
                List<SysMenuVO> childSysMenuList1 = menuVO.getChildSysMenuList();
                if(childSysMenuList1 != null && !childSysMenuList1.isEmpty()){
                    getMaps(list, sysCompanyGroup, menuVO, childSysMenuList1, menuIdGroup, menuPermissionIdGroup);
                }
            }
        }
        return list;
    }

    /**
     * 判断菜单是否勾选
     * @param menuIdGroup
     * @param menuId
     * @return
     */
    private boolean isMenuChecked(Map<String, List<SysMenuPermission>> menuIdGroup, String menuId) {
        boolean flag =false;
        if(menuIdGroup != null && !menuIdGroup.isEmpty()){
            List<SysMenuPermission> sysMenuPermissions = menuIdGroup.get(menuId);
            if(sysMenuPermissions != null && !sysMenuPermissions.isEmpty()){
                flag = true;
            }
        }
        return flag;
    }

    /**
     * 判断全部地区是否勾选
     * @param menuIdGroup
     * @param menuPermissionIdGroup
     * @param menuId
     * @return
     */
    private boolean isRegionChecked(Map<String, List<SysMenuPermission>> menuIdGroup, Map<String, List<SysCompanyPermission>> menuPermissionIdGroup, String menuId) {
        boolean flag = false;
        if(menuIdGroup != null && !menuIdGroup.isEmpty()){
            List<SysMenuPermission> sysMenuPermissions = menuIdGroup.get(menuId);
            if(sysMenuPermissions != null && !sysMenuPermissions.isEmpty()){
                for (SysMenuPermission sysMenuPermission : sysMenuPermissions) {
                    String menuPermissionId = sysMenuPermission.getMenuPermissionId();
                    if(menuPermissionIdGroup != null && !menuPermissionIdGroup.isEmpty()){
                        List<SysCompanyPermission> sysCompanyPermissions = menuPermissionIdGroup.get(menuPermissionId);
                        if(sysCompanyPermissions != null && !sysCompanyPermissions.isEmpty()){
                            flag = true;
                            break;
                        }
                    }
                }
            }
        }
        return flag;
    }

    /**
     * 判断省份是否勾选
     * @param menuIdGroup
     * @param menuPermissionIdGroup
     * @param menuId
     * @param sysCompanyS
     * @return
     */
    private boolean isProvinceChecked(Map<String, List<SysMenuPermission>> menuIdGroup, Map<String,
            List<SysCompanyPermission>> menuPermissionIdGroup, String menuId, List<SysCompany> sysCompanyS) {
        boolean flag = false;
        if(menuIdGroup != null && !menuIdGroup.isEmpty()){
            List<SysMenuPermission> sysMenuPermissions = menuIdGroup.get(menuId);
            if(sysMenuPermissions != null && !sysMenuPermissions.isEmpty()){
                //同一个权限组，同一个菜单，只对应一个菜单-权限组关联表主键
                String menuPermissionId = sysMenuPermissions.get(0).getMenuPermissionId();
                if(menuPermissionIdGroup != null && !menuPermissionIdGroup.isEmpty()){
                    List<SysCompanyPermission> sysCompanyPermissions = menuPermissionIdGroup.get(menuPermissionId);
                    if(sysCompanyPermissions != null && !sysCompanyPermissions.isEmpty()){
                        for (SysCompanyPermission sysCompanyPermission : sysCompanyPermissions) {
                            if(sysCompanyS.stream().anyMatch(sysCompany -> sysCompany.getCompanyId().equals(sysCompanyPermission.getCompanyId()))){
                                flag = true;
                                break;
                            }
                        }
                    }
                }
            }
        }
        return flag;
    }

    /**
     * 判断公司是否勾选
     * @param menuIdGroup
     * @param menuPermissionIdGroup
     * @param menuId
     * @param companyId
     * @return
     */
    private boolean isCompanyChecked(Map<String, List<SysMenuPermission>> menuIdGroup, Map<String,
            List<SysCompanyPermission>> menuPermissionIdGroup, String menuId, String companyId) {
        boolean flag = false;
        if(menuIdGroup != null && !menuIdGroup.isEmpty()){
            List<SysMenuPermission> sysMenuPermissions = menuIdGroup.get(menuId);
            if(sysMenuPermissions != null && !sysMenuPermissions.isEmpty()){
                //同一个权限组，同一个菜单，只对应一个菜单-权限组关联表主键
                String menuPermissionId = sysMenuPermissions.get(0).getMenuPermissionId();
                if(menuPermissionIdGroup != null && !menuPermissionIdGroup.isEmpty()){
                    List<SysCompanyPermission> sysCompanyPermissions = menuPermissionIdGroup.get(menuPermissionId);
                    if(sysCompanyPermissions != null && !sysCompanyPermissions.isEmpty()){
                        if(sysCompanyPermissions.stream().anyMatch(sysCompanyPermission -> sysCompanyPermission.getCompanyId().equals(companyId))){
                            flag = true;
                        }
                    }
                }
            }
        }
        return flag;
    }
}
